home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
tpxms.zip
/
XMS.DOC
< prev
next >
Wrap
Text File
|
1993-01-04
|
28KB
|
635 lines
Page 1
T P X M S v1.00
for Turbo Pascal v4.0 and above
Extended Memory Routines for HIMEM.SYS
Vernon E. Davis, Jr.
07/30/89
Page 2
Index ................................................. Page 2
Introduction to the XMS Specification ................. Page 3
Introduction to TPXMS.TPU ............................. Page 4
Type Declarations in TPXMS.TPU
Bit32Struct ........................................ Page 5
ExtMemMoveStruct ................................... Page 5
EMBHandleStruct .................................... Page 6
UMBSegmentStruct ................................... Page 6
Variable Declarations in TPXMS.TPU
isXMS .............................................. Page 7
XMSResult .......................................... Page 7
XMSError ........................................... Page 7
XMM_Control ........................................ Page 7
High Memory Routines
Procedure GetMemHMA ................................ Page 8
Procedure FreeMemHMA ............................... Page 8
Extended Memory Routines
Procedure QueryFreeMemXMS .......................... Page 9
Procedure QueryFreeBlockXMS ........................ Page 9
Function AllocExtMemBlockXMS ...................... Page 9
Procedure FreeExtMemBlockXMS ....................... Page 9
Procedure MoveExtMemBlockXMS ....................... Page 9
Function LockExtMemBlockXMS ....................... Page 10
Procedure UnlockExtMemBlockXMS ..................... Page 10
Procedure EMBHandleInfoXMS ......................... Page 10
Procedure ReallocExtMemBlockXMS .................... Page 10
Upper Memory Routines
Procedure ReqUpperMemBlockUMB ...................... Page 11
Procedure RelUpperMemBlockUMB ...................... Page 11
Miscellaneous Routines
Function XMSErrorMsg .............................. Page 12
Function ExistXMS ................................. Page 12
Procedure GetVerHiMem .............................. Page 12
Procedure GetRevHiMem .............................. Page 12
Procedure GlobalEnableA20 .......................... Page 12
Procedure GlobalDisableA20 ......................... Page 12
Procedure LocalEnableA20 ........................... Page 12
Procedure LocalDisableA20 .......................... Page 12
Procedure QueryA20 ................................. Page 12
Appendix A
Reading and Writing to the High Memory Area ......... Page 13
Appendix B
Reading and Writing with the Extended Memory Manager Page 14
Appendix C
XMS Error Codes ................................... Page 15
Page 3
INTRODUCTION TO THE XMS SPECIFICATION:
The XMS Specification, which is a Lotus/Intel/Microsoft/AST joint
venture, lays the groundwork for access to Extended Memory, the memory
above the 1-Megabyte boundary on AT-Class and above computer systems.
The heart of this is HIMEM.SYS; a device driver that loads at boot-time
from CONFIG.SYS and manages the complex task of reading from and writing
to Extended Memory.
This is not to be confused with the EMS Specification, which deals with
Expanded Memory on PC-Class and above computer systems. The EMS set of
rules govern a paging memory scheme that allow PC's to store large amounts
of data in EMS Memory without running out of DOS memory.
The routines of XMS allow access to Extended Memory for storing data
and, in some cases, actually running code; all from DOS. The problem of
switching from the Real Mode, which emulates the 8086/8088 processor, to
the Protected Mode, which allows access to the entire address space, and
back again is eliminated.
There are three classes of routines in XMS:
o High Memory Area (HMA) routines:
These allow access to the first 64K of Extended Memory. Data can be
store here and code can be executed.
o Extended Memory Management (XMM) routines:
These allow access to the entire physical address space of the
particular processor (80286 machines can access 16 Megabytes and
80386 machines can access 4 Gigabytes). Only data can be stored
and retrieved; no code can be executed.
o Upper Memory Block (UMB) routines:
These allow access to the area of memory between 640K and 1-Megabyte.
Most AT-Class machines come with at least 1024K of RAM.
NOTE: The HIMEM.SYS version, as of this writing, does not implement
these routines and little is known how they will react. The Speci-
fication does spell out how to call the routines, but they will not
function.
There are also routines to manipulate the address line A20 for access
to the first 64K of Extended Memory and routines for determining the
version and revision number of HIMEM.SYS.
The XMS Specification, which includes HIMEM.SYS and documentation, can
be obtained through a computer club or from the Microsoft Systems Forum on
CompuServe. The Official XMS Specification can be obtained directly from
Microsoft.
Page 4
INTRODUCTION TO TPXMS.TPU
The TPXMS.PAS source code is a Turbo Pascal v4.0 and above Unit that
utilizes the routines in HIMEM.SYS. When compiled, all the functions that
currently defined in the XMS Specification are easily accessable as Pascal
Procedures and Functions with Inline Machine Language calls to the XMM
Manager.
Included in this package ( TPXMS.ZIP ):
o TPXMS.PAS : the latest source code for TPXMS.TPU.
o XMSTEST.PAS : the latest source code for the TPXMS.TPU tests.
o TPXMS.DOC : this documentation.
Every effort has been taken to insure compatibility with both the
Specification and Turbo Pascal. As the Specification changes, so will
this package. Any comments about the XMS Specification should be directed
to Microsoft. Any comments concerning Turbo Pascal should be directed to
Borland International. Any comments concerning this package should be
directed to the author:
Vernon E. Davis, Jr.
17 Bowen Avenue
Woodstown, NJ 08098
CompuServe [71330,2705]
I release this package to the Public Domain. All I am asking for is
recognition for the amount of time and work that went into creating
this package.
Vernon E. Davis, Jr. 07/30/89
Page 5
TYPE DECLARATIONS IN TPXMS.TPU
** Bit32Struct = LongInt;
This is just a reminder that any value stored in this type should be
treated as an UNSIGNED 32-bit value. Turbo Pascal's LongInt type is a
SIGNED 32-bit number; however, any constant value assigned to this type
is stored as an UNSIGNED number.
Example:
Var lnum : LongInt;
lnum := $FFFFFFFF;
Write(lnum); ( the output displays -1 )
However, the actual variable is stored as $FFFFFFFF
The LongInt type has a range of -2,147,483,648 to +2,147,483,647. The
UNSIGNED number would be 4 Gigabytes or the actual address space of the
80386 processor. Very few people, if any, will need even 2 Gigabytes of
addressing, so this should not be a problem.
** ExtMemMoveStruct =
Record
Length : Bit32Struct; Number of bytes to transfer.
SourceHandle : Word; The Source Extended Memory Handle or 0.
SourceOffset : Bit32Struct; The offset into block in which to start.
DestHandle : Word; The Dest. Extended Memory Handle or 0.
DestOffset : Bit32Struct The offset into block in which to start.
End;
This structure sets up the movement of data from Conventional Memory to
Extended and visa-versa. According to the XMS Specifications, the move
can also occur from within Conventional Memory or Extended Memory. If
the SourceHandle or DestHandle is equal to zero, then it is considered
to be a Conventional Memory location, with the Segment:Offset pair placed
in the SourceOffset or DestOffset variable, respectively. The Extended
Memory Handle is obtained through the Allocate Function and the offset
is how far into the Extended Memory Block to start.
Example:
ExtMemMove : ExtMemMoveStruct;
XMSHandle : Word;
With ExtMemMove Do
Begin
Length := 4000; { move the entire video buffer }
SourceHandle := 0; { Conventional Memory Handle }
SourceOffset := $B8000000; { VIDEO = $B800:0000 }
DestHandle := XMSHandle; { obtained via AllocExtMemXMS }
DestOffset := 0 { start at offset 0 }
End;
When the MoveExtMemXMS Function is called, the contents of the video
screen would be written to Extended Memory. ( See the program XMSTEST.PAS
and Appendix B for actual code. )
Page 6
TYPE DECLARATIONS IN TPXMS.TPU ( continued )
** EMBHandleStruct =
Record
LockCount : Byte; The number of times that the block has been locked.
FreeHandles : Byte; The number of remaining Extended Memory Handles.
BlockLenKB : Word The length, in kilobytes, of the current Extended
Memory Block.
End;
This structure is used by the EMBHandleInfoXMS procedure to extract
information about a particular Extended Memory Block.
** UMBSegmentStruct =
Record
Segment : Word; The segment to which the Upper Memory Block has
been assigned.
UMBSizePG : Word The actual size of the Upper Memory Block in
paragraphs (1 paragraph = 16 bytes).
End;
Please note that this structure is defined, but the functions in the
current revision of HIMEM.SYS (2.06) does not access the Upper Memory
Block. All of these functions return $80 (Function not implemented).
Page 7
VARIABLE DECLARATIONS IN TPXMS.TPU
** isXMS : Boolean; TRUE if HIMEM.SYS is correctly
installed. NOTE: All Procedures/
Functions in TPXMS.TPU check for isXMS
equal TRUE. If NOT TRUE, XMSResult
equals 0 and XMSError equals $80.
** XMSResult : Word; Equals 1 if the Function called is
successful, else 0. Some of these
functions do not use this as a result;
instead it is used to return a value
from the Function.
** XMSError : Byte; If XMSResult = 0 and this byte is
greater or equal to $80, an error
has occurred. See the Appendix C
for an explanation of each value.
** XMM_Control : Array[0..1] of Word; This is the holder of the actual
address of the XMM_Control Function.
The Offset is contained in [0] and
the Segment is contained in [1]. This
is really an internal variable and has
no other use outside the XMS Functions.
Page 8
HIGH MEMORY ROUTINES
** Procedure GetMemHMA(Word);
This procedure attempts to allocate the High Memory Area with the Word
value passed. Check XMSResult = 1 for success. NOTE: If the /HMAMIN=
parameter is greater than the amount of memory requested, the procedure
will fail. ( See the XMS Specifications for more detail. ) NOTE: If
this procedure is called, the FreeMemHMA procedure MUST be called to
free the HMA before the program terminates or other programs cannot use
that memory. ( See Appendix A for reading and writing to the HMA. )
** Procedure FreeMemHMA;
This procedure will attempt to release the High Memory Area. Check
XMSResult = 1 for success. NOTE: This function MUST be called to free
up the HMA before the program terminates or other programs will not
have access to the memory.
Page 9
EXTENDED MEMORY ROUTINES
** Procedure QueryFreeMemXMS;
This procedure returns the TOTAL amount of free Extended Memory available
for access. The value is returned in XMSResult in kilobyte increments.
Example:
QueryFreeMemXMS;
Write(XMSResult);
(The screen displays 256, which means there is a total of 256K
of Extended Memory available for access.)
** Procedure QueryFreeBlockXMS;
This procedure returns the LARGEST BLOCK of Extended Memory available
for access. The value is returned in XMSResult in kilobyte increments.
Example:
QueryFreeBlockXMS;
Write(XMSResult);
(The screen displays 64, which means the largest block of Extended
Memory available is 64K.)
** Function AllocExtMemBlockXMS(Word) : Word;
This function attempts to allocate a block of Extended Memory for data
storage. If XMSResult = 1 (success), then the value returned from the
function is the Extended Memory Handle to be used in reference to the
allocated block. The Word value passed to the function is the amount
of memory to allocate in kilobytes. Remember that the block must be
released before the program terminates or that block will remain in
memory and cannot be accessed again. If XMSResult = 0 (failure), do not
attempt to use the handle. ( See Appendix B for actual code. )
** Procedure FreeExtMemBlockXMS(Word);
This procedure releases a block of Extended Memory that was previously
allocated. The Word value passed to the procedure is the Extended Memory
Handle of the allocated block. This procedure must be called to release
a previously allocated block before the program terminates or the memory
that the block resides in is lost. Check XMSResult = 1 for success.
( See Appendix B for actual code. )
** Procedure MoveExtMemBlockXMS(Var ExtMemMoveStruct);
This procedure moves data from Conventional Memory to Extended Memory and
visa-versa. The structure passed to the procedure contains the data
length and source/destination addresses. The structure type is defined
in the TPU Type Declarations. ( See the Type Declarations above. )
Check XMSResult = 1 for success. ( See Appendix B for actual code. )
Page 10
HIGH MEMORY ROUTINES ( continued )
** Function LockExtMemBlockXMS(Word) : Bit32Struct;
This function attempts to lock an allocated Extended Memory Block; that
is; making the block unmovable. If there are numerous unlocked blocks
in Extended Memory and one or more of those blocks are released, the XMM
Manager moves the other blocks around to create one large free block of
memory. This function prevents the block in question from being moved
from its location in memory. The Word value passed is the Extended Memory
Handle of the allocated block. The Bit32Struct value returned is the
linear (actual) address of the block. Check XMSResult = 1 for success.
* IMPORTANT * A block can be locked more than once. The Lock Count,
which can be obtained with the EMBHandleInfoXMS procedure, is increased
by one each time the LockExtMemBlockXMS function is called, up to a
maximum of 255 times. In order for a block to be released, its Lock Count
MUST be zero. Use the UnlockExtMemBlockXMS procedure to decrease the Lock
Count.
** Procedure UnlockExtMemBlockXMS(Word);
This procedure reduces the Lock Count of a locked Extended Memory Block
by one. Because a block can be locked more than once, this routine must
be called until the Lock Count, obtained through the EMBHandleInfoXMS
procedure, is zero before the block can be released. The Word value
passed to the procedure is the Extended Memory Handle. Check XMSResult
= 1 for success.
** Procedure EMBHandleInfoXMS(Word; Var EMBHandleStruct);
This procedure gathers information about a particular Extended Memory
Block and about the XMM environment. The Word value passed to the
procedure is the Extended Memory Handle. The structure passed to the
procedure will contain the following information after returning from
the call:
o The Lock Count: the number of times that this block has been
locked via the LockExtMemBlockXMS procedure. If this value is
zero then the block can be successfully released with the
FreeExtMemBlockXMS procedure.
o The Free Handle Count: the number of free Extended Memory Handles
that are available. If HIMEM.SYS was loaded without the /NUMHANDLES=
parameter, then there are a total of 32 handles available.
o The Block Size: this value, in kilobytes, is the current size of
the block in question.
Check XMSResult = 1 for success.
** Procedure ReallocExtMemBlockXMS(Word; Word);
This procedure will attempt to change the current size of the particular
Extended Memory Block. The first Word value passed to the procedure is
the Extended Memory Handle. The second Word value passed to the procedure
is the new size, in kilobytes, of the block.
* NOTE * As of this writing, this procedure is not functional. It is a
result of HIMEM.SYS, not the source code. If called, XMSResult will
contain 0 and the value in XMSError will be $80 (Function not implemented).
When HIMEM.SYS is updated, this procedure should work as planned and
the TPXMS.TPU need not be recompiled.
Page 11
UPPER MEMORY ROUTINES
** Procedure ReqUpperMemBlockUMB(Word; Var UMBSegmentStruct);
This procedure attempts to allocate an Upper Memory Block. The Word value
passed to the procedure is the amount of memory to allocate in paragraphs
( 1 paragraph = 16 bytes ). The structure passed to the procedure will
contain the following information after returning from the call:
o The Segment : the segment of the UMB.
o The Block Size : the actual size of the UMB in paragraphs.
* NOTE * As of this writing, this procedure is not functional. It is a
result of HIMEM.SYS, not the source code. If called, XMSResult will
contain 0 and the value in XMSError will be $80 (Function not implemented).
When HIMEM.SYS is updated, this procedure should work as planned and
the TPXMS.TPU need not be recompiled.
** Procedure RelUpperMemBlockUMB(Word);
This procedure releases a previously allocated Upper Memory Block. The
Word value passed to the procedure is the Segment of the UMB.
* NOTE * As of this writing, this procedure is not functional. It is a
result of HIMEM.SYS, not the source code. If called, XMSResult will
contain 0 and the value in XMSError will be $80 (Function not implemented).
When HIMEM.SYS is updated, this procedure should work as planned and
the TPXMS.TPU need not be recompiled.
Page 12
MISCELLANEOUS ROUTINES
** Function XMSErrorMsg : String;
This function is not part of the XMS Specification, but is provided as
convienence to the programmer in intrepreting Error Codes returned by
the XMM_Control Function. A text message is returned based on the value
in the XMSError byte. Example: If XMSResult = 0 Then Writeln(XMSErrorMsg);
** Function ExistXMS : Boolean;
This Function is called once in the TPU and really does not need to be
called again. It sets the variable isXMS TRUE if HIMEM.SYS is properly
loaded and loads the XMM_Control array with the address of XMM_Control.
** Procedure GetVerHiMem;
This procedure retrieves the version number of HIMEM.SYS in XMSResult.
** Procedure GetRevHiMem;
This procedure retrieves the revision number of HIMEM.SYS in XMSResult.
** Procedure GlobalEnableA20;
This toggles the address line A20 high so that access to the High Memory
Area is obtained. THIS PROCEDURE MUST BE CALLED to access the HMA or
the system will hang when trying to write to it. ( See Appendix A for
actual code. ) The GlobalDisableA20 procedure MUST be called BEFORE
releasing the HMA and BEFORE the program terminates. Check XMSResult = 1
for success.
** Procedure GlobalDisableA20;
This toggles the address line A20 low. This procedure MUST be called
BEFORE releasing the HMA and BEFORE the program terminates. Check
XMSResult = 1 for success.
** Procedure LocalEnableA20;
This toggles the address line A20 high so that access to the first 64K
of Extended Memory is obtained. THIS PROCEDURE MUST BE CALLED to access
the memory or the system will hang when trying to write to it. ( See
Appendix A for actual code. ) The LocalDisableA20 procedure MUST be
called BEFORE the program terminates. Check XMSResult = 1 for success.
* IMPORTANT * This procedure allows the bypass of the HMA access routines.
Therefore, if there is another program, such as a TSR, in the HMA area,
and Extended Memory is directly written to, that program in the HMA could
be destroyed. One possible way to check if the HMA is in use would be to
call the QueryA20 procedure to determine if address line A20 is active.
Another way would be to attempt to allocate the HMA by calling the
GetMemHMA procedure. In short, use the LocalEnableA20 procedure at the
risk of hanging the system.
** Procedure LocalDisableA20;
This toggles the address line A20 low. This procedure MUST be called
BEFORE the program terminates. Check XMSResult = 1 for success.
** Procedure QueryA20;
This procedure determines the status of address line A20.
If XMSResult = 1 then A20 is active (enabled).
If XMSResult = 0 then A20 is inactive (disabled).
Page 13
Appendix A - Reading and Writing to the High Memory Area ( HMA )
The HMA can be directly accessed by DOS and Turbo Pascal. The address of
the HMA officially begins at $FFFF:$0010 and ends at $FFFF:$FFFF, giving
a total memory capacity of 65520 bytes ( 64K - 16 bytes ). Study the
following piece of code:
Program HMA_R_W;
(*
NOTE: This program assumes that HIMEM.SYS is properly loaded and that
there is 64Kbytes free in the HMA area.
*)
Uses
CRT,DOS,TPXMS;
Var
vid : Byte Absolute $B800:$0000;
hma : Byte Absolute $FFFF:$0010;
i : Integer;
Begin
GetMemHMA($FFFF); { Reserve all of the HMA }
GlobalEnableA20; { Toggle the A20 address line high }
ClrScr; { Clear the screen }
For i := 1 To 1999 Do
Write('A'); { Fill the screen with "A" }
Move(vid,hma,4000); { Copy the contents of the screen to HMA }
ClrScr; { Clear the screen }
Move(hma,vid,4000); { Restore the screen from HMA }
GlobalDisableA20; { Toggle the A20 address line low }
FreeMemHMA { Release the HMA }
End.
The HMA can be bypassed by reading and writing to Direct Memory in the
same fashion using the LocalEnable/DisableA20 procedures. However, any
program, such as a TSR currently running in the HMA area, could be over-
written. Use of this method is not recommended unless it is an absolute
certainty that there is nothing in the HMA.
Program DMA_R_W;
(*
NOTE: This program assumes that HIMEM.SYS is properly loaded.
*)
Uses
CRT,DOS,TPXMS;
Var
vid : Byte Absolute $B800:$0000;
dma : Byte Absolute $FFFF:$0010;
i : Integer;
Begin
LocalEnableA20; { Toggle the A20 address line high }
ClrScr; { Clear the screen }
For i := 1 To 1999 Do
Write('A'); { Fill the screen with "A" }
Move(vid,dma,4000); { Copy the contents of the screen to HMA }
ClrScr; { Clear the screen }
Move(dma,vid,4000); { Restore the screen from HMA }
LocalDisableA20 { Toggle the A20 address line low }
End.
Page 14
Appendix B - Reading and Writing with the Extended Memory Manager ( XMM )
The XMM routines provide access to Extended Memory that is transparent
to the programmer in switching from Real Mode to Protected Mode and back
again. Study the following piece of code:
Program XMM_R_W;
(*
NOTE: This program assumes that HIMEM.SYS is properly loaded and that
there is 4Kbytes free in Extended Memory.
*)
Uses
CRT,DOS,TPXMS;
Var
XMSHandle : Word;
ExtMemMove : ExtMemMoveStruct;
i : Integer;
Begin
XMSHandle := AllocExtMemBlockXMS(4); { Allocate 4 kilobytes }
With ExtMemMove Do { Load the structure }
Begin
Length := 4000; { Size of video screen }
SourceHandle := 0; { Use Conventional Memory }
SourceOffset := $B8000000; { VIDEO = $B800:$0000 }
DestHandle := XMSHandle; { Extended Memory Handle }
DestOffset := 0 { Offset 0 into the block }
End;
ClrScr; { Clear the screen }
For i := 1 To 1999 Do Write('A'); { Fill the screen with "A" }
MoveExtMemBlockXMS(ExtMemMove); { Move screen to Ext. Memory }
ClrScr; { Clear the screen }
With ExtMemMove Do { Load the structure }
Begin
Length := 4000; { Size of video screen }
SourceHandle := XMSHandle; { Extended Memory Handle }
SourceOffset := 0; { Offset 0 into the block }
DestHandle := 0; { Use Conventional Memory }
DestOffset := $B8000000 { VIDEO = $B800:$0000 }
End;
MoveExtMemBlockXMS(ExtMemMove); { Restore screen from Ext. Mem. }
FreeExtMemBlockXMS(XMSHandle) { Release Extended Memory Block }
End.
Page 15
Appendix C - XMS ERROR CODES
If XMSResult = 0 and XMSError is greater than or equal to $80 then
an error has occurred. The following codes are valid as of this
writing:
$80 : XMS Function not implemented
$81 : VDISK detected
$82 : A20 Error
$8E : General Driver Error
$8F : Unrecoverable Driver Error
$90 : HMA does not exist
$91 : HMA in use by another process
$92 : Memory requested less than /HMAMIN= parameter
$93 : HMA not allocated
$94 : A20 is enabled
$A0 : All of Extended Memory is allocated
$A1 : No Extended Memory Handles available
$A2 : Extended Memory Handle is invalid
$A3 : Extended Move Structure: Source Handle is invalid
$A4 : Extended Move Structure: Source Offset is invalid
$A5 : Extended Move Structure: Destination Handle is invalid
$A6 : Extended Move Structure: Destination Offset is invalid
$A7 : Extended Move Structure: Length is invalid
$A8 : Extended Move Structure: Move has invalid overlap
$A9 : Parity Error
$AA : Block is not locked
$AB : Block is locked
$AC : Block Lock Count has overflowed
$AD : Block Lock has failed
$B0 : A smaller Upper Memory Block is available
$B1 : No Upper Memory Blocks are available
$B2 : Upper Memory Block Segment Number is invalid